package com.xqls.service.impl;


import com.xqls.bean.*;
import com.xqls.biz.OperationRecordBiz;
import com.xqls.dal.dao.TScheduleJobDao;
import com.xqls.dal.model.Remotecontrol;
import com.xqls.dal.model.TScheduleJob;
import com.xqls.dal.model.TScheduleJobExample;
import com.xqls.redis.Constants;
import com.xqls.redis.RedisCache;
import com.xqls.redis.RedisKeyEnum;
import com.xqls.redis.lock.RedisLockHelper;
import com.xqls.server.dto.SoketCommonDto;
import com.xqls.server.dto.send.ConcentrationSamplingSetDto;
import com.xqls.server.dto.send.SingleSampleSamplingSetDto;
import com.xqls.server.dto.send.SpecialSamplingSetDto;
import com.xqls.server.dto.send.SwitchValveDto;
import com.xqls.server.netty.NettyTCPServer;
import com.xqls.server.netty.future.SyncWriteFuture;
import com.xqls.server.netty.future.SyncWriteMap;
import com.xqls.server.netty.future.WriteFuture;
import com.xqls.service.*;
import com.xqls.util.CommonResult;
import com.xqls.util.DictionaryEnums;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class SokectServiceImpl implements SokectService {
	 private static Logger logger = Logger.getLogger(SokectServiceImpl.class);
    @Autowired private RemotecontrolService remoteService;
    @Autowired private DischargeRealdataService dischargeService;
    @Autowired private PublicStormwaterRealdataService publicStormwaterRealdataService;   //STORMWATER
    @Autowired private RainwaterDischargeRealdataService rainwaterService;
	@Autowired private OperationRecordBiz operationBiz;
	@Autowired private RedisCache<String, Object> redisCache;
	@Autowired private TScheduleJobDao tScheduleDao;

    @Autowired private  CompanyService  companyService;
	@Override
	public CommonResult sendData(SoketCommonDto soketCommonDto) {
		RedisLockHelper.RedisLock redisLock=null;
		CommonResult result = new CommonResult();
		try {
			Channel channel = NettyTCPServer.getChannelByAdresss(soketCommonDto.getAdress());
			if (channel == null) {
				result.setResultMsg(soketCommonDto.getDeviceName()+"未找到对应的客户端");
				return result;
			}

			redisLock=  RedisLockHelper.getInstance().newLock(soketCommonDto.getAdress()+"send",60000);
			if(!redisLock.tryLock()){
				result.setResultMsg(soketCommonDto.getDeviceName()+"设备正在操作");
				return result;
			}
			// 发送数据到客户端
			final	WriteFuture<SoketCommonDto> writeFuture = new SyncWriteFuture(soketCommonDto.getAdress());
			SyncWriteMap.writeRecords.put(soketCommonDto.getAdress(), writeFuture);
			ChannelFuture future = channel.writeAndFlush(soketCommonDto); // 返回值类型为ChannelFuture
			send(writeFuture,future);

			SoketCommonDto response = writeFuture.get(60000, TimeUnit.MILLISECONDS);//等待60000毫秒
			SyncWriteMap.writeRecords.remove(writeFuture.requestId());
			if(response !=null){
				if(soketCommonDto  instanceof ConcentrationSamplingSetDto|| soketCommonDto instanceof SpecialSamplingSetDto) {
					final	WriteFuture<SoketCommonDto>	writeFutureTwo = new SyncWriteFuture(soketCommonDto.getAdress());
					SyncWriteMap.writeRecords.put(soketCommonDto.getAdress(), writeFutureTwo);
					future =channel.writeAndFlush(soketCommonDto);
					send(writeFutureTwo,future);
					response = writeFutureTwo.get(60000, TimeUnit.MILLISECONDS);//等待60000毫秒
					SyncWriteMap.writeRecords.remove(writeFutureTwo.requestId());
					if(response!=null){
						SyncWriteMap.writeRecords.put(soketCommonDto.getAdress(), writeFuture);
						result.setIsSuccess(true);
					}

				}else {
					result.setIsSuccess(true);
				}

			}else{
				result.setResultMsg(soketCommonDto.getDeviceName()+"设备未返回结果");
				return result;
			}

		} catch (Exception e) {
			logger.error("发送数据异常",e);
		}finally {
			if(redisLock!=null)
			redisLock.unlock();
		}

		return result;
	}

	private  void send(WriteFuture<SoketCommonDto> writeFuture,	ChannelFuture future){
		future.addListener(new ChannelFutureListener() {
			// write操作完成后调用的回调函数
			@Override
			public void operationComplete(ChannelFuture future) throws Exception {
				writeFuture.setWriteResult(future.isSuccess());
				writeFuture.setCause(future.cause());
				if (!writeFuture.isWriteSuccess()) {
					SyncWriteMap.writeRecords.remove(writeFuture.requestId());
				}
			}
		});

	}


    public CommonResult sendSwitchValve(String address, Integer anger,String type,Integer rainWaterTime) {
        TScheduleJob tScheduleJob = new TScheduleJob();
        TScheduleJobExample example = new TScheduleJobExample();
        UserBean userBean=(UserBean)redisCache.get(Constants.getRedisKey(RedisKeyEnum.USER_SESSION,SecurityUtils.getSubject().getPrincipal().toString()));
        String name = userBean.getName();
        CommonResult commonResult=new CommonResult();
        SwitchValveDto switchValveDto = new SwitchValveDto();
        switchValveDto.setAngle(anger);
        switchValveDto.setAdress(address);
        CommonResult  result=companyService.queryByDeviceNo(address);
        if(!result.getIsSuccess()){
            result.setResultMsg(address+"未找到对应的企业设备");
            return  result;
        }
        CompanyBean companyBean=(CompanyBean)result.getData();
        switchValveDto.setDeviceName(companyBean.getCompanyName());

        String valveState;
        Integer valveSetting;
        Remotecontrol remotecontrol=  remoteService.selectMaxTimeByDeviceNo(address,type);
        boolean ignore =false;
        //如果上一次设置参数的时间超过半小时 则可以重新设置
        if(remotecontrol!=null ){
            ignore =System.currentTimeMillis()-remotecontrol.getRecordingTime().getTime()>180000;
            valveSetting=remotecontrol.getValveSetting();
            if(type.equals("discharge")){
                DischargeRealdataBean dischargeRealdataBean=dischargeService.queryByDeviceNo(address);
                if(dischargeRealdataBean!=null){
                    valveState=dischargeRealdataBean.getValveState();
                    if(StringUtils.isNotEmpty(valveState)&&valveSetting!=null) {
                        if(Math.abs(Integer.parseInt(valveState)-valveSetting)>10&&!ignore){
                            commonResult.setResultMsg(switchValveDto.getDeviceName()+"阀门状态与设定状态不一致");
                            return commonResult;
                        }
                    }
                }
            }else if(type.equals("rainwater")){
                RainwaterDischargeRealdataBean rainwaterDischargeRealdataBean=rainwaterService.queryByDeviceNo(address);
                if(rainwaterDischargeRealdataBean!=null){
                    valveState=rainwaterDischargeRealdataBean.getValveRealtime();
                    if(StringUtils.isNotEmpty(valveState)&&valveSetting!=null){
                        String valveSettingStr;
                        if(remotecontrol.getValveSetting()==DictionaryEnums.OPEN_VALVE.getCode()){
                            valveSettingStr="开";
                        }else{
                            valveSettingStr="关";
                        }
                        if(!valveState.equals(valveSettingStr)&&!ignore){
                            commonResult.setResultMsg(switchValveDto.getDeviceName()+"阀门状态与设定状态不一致");
                            return commonResult;
                        }
                    }
                }
            }
        }

        if(type.equals("discharge")){
            operationBiz.save(address, DictionaryEnums.DISCHARGE.getCode(), DictionaryEnums.OPERATION.getCode().toString(), name+"下发开启阀门指令，阀门角度为："+anger, address);
        }else if(type.equals("rainwater")){
            operationBiz.save(address, DictionaryEnums.RAINWATER.getCode(), DictionaryEnums.VALVE_OPERATION.getCode().toString(), name+"下发开启阀门指令，阀门角度为："+anger, address);
        }
       
       commonResult=sendData(switchValveDto);
       if(commonResult.getIsSuccess()){
    	   if(type.equals("rainwater")){
        	   if(anger==99){//企业雨水排放口传入，如果开阀门，anger=99；关阀门anger=0
                   tScheduleJob = setScheduleJob(rainWaterTime,address);

                   example.createCriteria().andFDescriptionEqualTo(tScheduleJob.getfDescription());
                   List<TScheduleJob> list = tScheduleDao.selectJobByExample(example);
                   if(list!=null && list.size()>0){
                       tScheduleDao.updateJob(tScheduleJob);
                   }else{
                       tScheduleDao.insertJob(tScheduleJob);
                   }

               }
           }
       }
        return  commonResult;
    }

    @Override
    public void closeValve(String address) {
        SwitchValveDto switchValveDto = new SwitchValveDto();
        switchValveDto.setAngle(0);
        switchValveDto.setAdress(address);
        sendData(switchValveDto);
    }



	  //设置触发器参数
    public TScheduleJob setScheduleJob(Integer rainWaterTime,String address) {
    	TScheduleJob tScheduleJob = new TScheduleJob();
    	tScheduleJob.setfCronExpression(createCronExpression(rainWaterTime));
    	tScheduleJob.setfDescription("触发器"+address);
    	tScheduleJob.setfIsConcurrent("no");//是否并发
    	tScheduleJob.setfJobName(address);
    	tScheduleJob.setfJobGroup(Scheduler.DEFAULT_GROUP);
    	tScheduleJob.setfBeanClass("com.xqls.quaz.ValveControlJob");//定时调用的方法
    	tScheduleJob.setfJobStatus("running");//任务运行状态
    	tScheduleJob.setfMethodName("valveControl");//要执行的方法
    	tScheduleJob.setfSpringId("CronTriggerBeanValve"+address);
    	tScheduleJob.setfTimes(rainWaterTime);
    	return tScheduleJob;
    }

    public String createCronExpression(Integer rainWaterTime){
    	String expression = null;
    	int day1 = 0;
    	int hour1 = 0;
    	Calendar now = Calendar.getInstance();
    	int year = now.get(Calendar.YEAR);
    	int month = (now.get(Calendar.MONTH))+1;
    	int day = now.get(Calendar.DAY_OF_MONTH);
    	int hour = now.get(Calendar.HOUR_OF_DAY);
    	int minute = now.get(Calendar.MINUTE);
    	int second = now.get(Calendar.SECOND);
    	if((rainWaterTime+hour)>=24){
    		day1 = day+(rainWaterTime+hour)/24;
    		hour1 = (rainWaterTime+hour)%24;
    	}else{
    		day1 = day;
    		hour1 = hour+rainWaterTime;
    	}
    	expression = second+" "+minute+" "+hour1+" "+day1+" "+month+" ? "+year;
    	return expression;
    }

	/**
	 * 采样仪采样设置
	 *
	 * @return
	 */
	public CommonResult samplingSetSend(Remotecontrol remotecontrol,SoketCommonDto samplingSetDto,String sendType,String remoteType) {
		UserBean userBean=(UserBean)redisCache.get(Constants.getRedisKey(RedisKeyEnum.USER_SESSION,SecurityUtils.getSubject().getPrincipal().toString()));
		String name = userBean.getName();
		CommonResult commonResult=new CommonResult();
        //上一次设定的状态
        String adress=samplingSetDto.getAdress();
		CommonResult  result=companyService.queryByDeviceNo(adress);
		if(!result.getIsSuccess()){
			result.setResultMsg(adress+"未找到对应的企业设备");
			return  result;
		}
		CompanyBean companyBean=(CompanyBean)result.getData();
		samplingSetDto.setDeviceName(companyBean.getCompanyName());
        String state=null;//当前采样仪的状态
        if(!(samplingSetDto instanceof SingleSampleSamplingSetDto) &&(sendType.equals("samplingSetSend")||sendType.equals("Reset"))){
            if(remoteType.equals("discharge")){
                DischargeRealdataBean dischargeRealdataBean=dischargeService.queryByDeviceNo(adress);
                if(dischargeRealdataBean!=null)state=dischargeRealdataBean.getSamplingState();
            }else if(remoteType.equals("stormwater")){
                PublicStormwaterRealdataBean publicStormwaterRealdataBean=publicStormwaterRealdataService.queryByDeviceNo(adress);
                if(publicStormwaterRealdataBean!=null)state=publicStormwaterRealdataBean.getState();
            }else if(remoteType.equals("rainwater")){//企业雨水
                RainwaterDischargeRealdataBean rainwaterDischargeRealdataBean=rainwaterService.queryByDeviceNo(adress);
                if(rainwaterDischargeRealdataBean!=null)state=rainwaterDischargeRealdataBean.getSamplingState();
            }
            if(state!=null){
            switch (sendType){
				case "samplingSetSend":

					 if(!"空闲".equals(state)){
						 commonResult.setResultMsg(samplingSetDto.getDeviceName()+"设备状态为启动,请稍等");
						 return  commonResult;
					 }
					break;
				case "Reset":
					if(!"启动".equals(state)){
						commonResult.setResultMsg(samplingSetDto.getDeviceName()+"设备状态已经为空闲");
						return  commonResult;
					}
					break;

            }

            }
        }





        // 2017/3/14 发送采样设置 记录操作记录
		if(sendType.equals("samplingSetSend")){
			if(remoteType.equals("discharge")){
				commonResult=operationBiz.save(samplingSetDto.getAdress(), DictionaryEnums.DISCHARGE.getCode(), DictionaryEnums.OPERATION.getCode().toString(), publicModeOperation(remotecontrol)+publicSamOperation(remotecontrol), samplingSetDto.getAdress());
			}else if(remoteType.equals("stormwater")){
				commonResult=operationBiz.save(samplingSetDto.getAdress(), DictionaryEnums.STORMWATER.getCode(), DictionaryEnums.OPERATION.getCode().toString(),publicModeOperation(remotecontrol)+publicSamOperation(remotecontrol), samplingSetDto.getAdress());
			}else if(remoteType.equals("rainwater")){//企业雨水
				commonResult=operationBiz.save(samplingSetDto.getAdress(), DictionaryEnums.RAINWATER.getCode(), DictionaryEnums.VALVE_OPERATION.getCode().toString(),rainWater(remotecontrol), samplingSetDto.getAdress());
			}
		}else if(sendType.equals("Reset")){
			if(remoteType.equals("discharge")){
				commonResult=operationBiz.save(samplingSetDto.getAdress(),  DictionaryEnums.DISCHARGE.getCode(), DictionaryEnums.OPERATION.getCode().toString(), name+"下发排放口采样仪复位指令", samplingSetDto.getAdress());
			}else if(remoteType.equals("stormwater")){
				commonResult=operationBiz.save(samplingSetDto.getAdress(), DictionaryEnums.STORMWATER.getCode(), DictionaryEnums.OPERATION.getCode().toString(), name+"下发公共雨水排放口采样仪复位指令", samplingSetDto.getAdress());
			}else if(remoteType.equals("rainwater")){
				commonResult=operationBiz.save(samplingSetDto.getAdress(), DictionaryEnums.RAINWATER.getCode(), DictionaryEnums.VALVE_OPERATION.getCode().toString(), name+"下发企业雨水排放口采样仪复位指令", samplingSetDto.getAdress());
			}
		}else if(sendType.equals("calibration")){
			if(remoteType.equals("intake")){
				commonResult=operationBiz.save(samplingSetDto.getAdress(), DictionaryEnums.INTAKE.getCode(), DictionaryEnums.OPERATION.getCode().toString(), name+"对取水口时间校验", samplingSetDto.getAdress());
			}else if(remoteType.equals("discharge")){
				commonResult=operationBiz.save(samplingSetDto.getAdress(), DictionaryEnums.DISCHARGE.getCode(), DictionaryEnums.OPERATION.getCode().toString(), name+"对排放口时间校验", samplingSetDto.getAdress());
			}else if(remoteType.equals("stormwater")){
				commonResult=operationBiz.save(samplingSetDto.getAdress(), DictionaryEnums.STORMWATER.getCode(), DictionaryEnums.OPERATION.getCode().toString(), name+"对公共雨水排放口时间校验", samplingSetDto.getAdress());
			}else if(remoteType.equals("rainwater")){
				commonResult=operationBiz.save(samplingSetDto.getAdress(), DictionaryEnums.RAINWATER.getCode(), DictionaryEnums.VALVE_OPERATION.getCode().toString(), name+"对企业雨水排放口时间校验", samplingSetDto.getAdress());
			}
		}else if(sendType.equals("valveChange")){//系统配置中的阀门控制
			if(remoteType.equals("discharge")){
				if(remotecontrol.getControlModel().equals("自动控制")){
					commonResult=operationBiz.save(samplingSetDto.getAdress(), DictionaryEnums.DISCHARGE.getCode(), DictionaryEnums.OPERATION.getCode().toString(), "阀门控制模式："+remotecontrol.getControlModel()+",高液位报警值："+remotecontrol.getHighLevel()+",低液位报警值："+remotecontrol.getLowLevel()+",故障处理方式："+remotecontrol.getTreatment(), samplingSetDto.getAdress());
				}else{
					commonResult=operationBiz.save(samplingSetDto.getAdress(), DictionaryEnums.DISCHARGE.getCode(), DictionaryEnums.OPERATION.getCode().toString(), "阀门控制模式："+remotecontrol.getControlModel()+",故障处理方式："+remotecontrol.getTreatment(), samplingSetDto.getAdress());
				}
			}else if(remoteType.equals("stormwater")){
				if(remotecontrol.getControlModel().equals("自动控制")){
					commonResult=operationBiz.save(samplingSetDto.getAdress(), DictionaryEnums.STORMWATER.getCode(), DictionaryEnums.OPERATION.getCode().toString(), "阀门控制模式："+remotecontrol.getControlModel()+",高液位报警值："+remotecontrol.getHighLevel()+",低液位报警值："+remotecontrol.getLowLevel()+",故障处理方式："+remotecontrol.getTreatment(), samplingSetDto.getAdress());
				}else{
					commonResult=operationBiz.save(samplingSetDto.getAdress(), DictionaryEnums.STORMWATER.getCode(), DictionaryEnums.OPERATION.getCode().toString(), "阀门控制模式："+remotecontrol.getControlModel()+",故障处理方式："+remotecontrol.getTreatment(), samplingSetDto.getAdress());
				}
			}
		}






		commonResult=sendData(samplingSetDto);
		return commonResult;
	}

	/**
	 * 单次采样量，采样周期公共方法
	 * @param remotecontrol
	 * @return
	 */
	public String publicSamOperation(Remotecontrol remotecontrol){
		String operation = null;
		operation = "单次采样量："+remotecontrol.getSingleSamplingQuantity()+"ml,采样周期："+remotecontrol.getSamplingInterval()+"分钟";
		return operation;
	}
	/**
	 * 采样模式、总采样时间、启动方式、累计流量、延时公共方法
	 * @param remotecontrol
	 * @return
	 */
	public String publicModeOperation(Remotecontrol remotecontrol){
		UserBean userBean=(UserBean)redisCache.get(Constants.getRedisKey(RedisKeyEnum.USER_SESSION,SecurityUtils.getSubject().getPrincipal().toString()));
		String name = userBean.getName();

		String operation = null;
		if(remotecontrol.getStartupMode()==null){
			operation = name+"下发"+DictionaryEnums.find(Integer.parseInt(remotecontrol.getSamplingMode())).getMsg()+"指令，累计流量："+remotecontrol.getCumulativeFlow()+"ml，总采样时间："+remotecontrol.getSamplingTotaltime()+"小时";
		}else{
			if(remotecontrol.getStartupMode().intValue()==DictionaryEnums.RESTART_NOW.getCode().intValue()){//立即启动
				operation = name+"下发"+DictionaryEnums.find(Integer.parseInt(remotecontrol.getSamplingMode())).getMsg()+"指令，启动方式："+DictionaryEnums.RESTART_NOW.getMsg()+"累计流量："+remotecontrol.getCumulativeFlow()+"ml，总采样时间："+remotecontrol.getSamplingTotaltime()+"小时";
			}else{//延时启动
				operation = name+"下发"+DictionaryEnums.find(Integer.parseInt(remotecontrol.getSamplingMode())).getMsg()+"指令，启动方式："+DictionaryEnums.DELAYED_START.getMsg()+"，延时："+remotecontrol.getDelayed()+"小时，累积流量"+remotecontrol.getCumulativeFlow()+"ml，总采样时间："+remotecontrol.getSamplingTotaltime()+"小时";
			}
		}

		return operation;
	}
	/**
	 * 雨水采样记录操作记录
	 * @param remotecontrol
	 * @return
	 */
	public String rainWater(Remotecontrol remotecontrol){
		UserBean userBean=(UserBean)redisCache.get(Constants.getRedisKey(RedisKeyEnum.USER_SESSION,SecurityUtils.getSubject().getPrincipal().toString()));
		String name = userBean.getName();
		String operation = null;
		if(remotecontrol.getValveSetting()==45){
			operation = name+"下发开阀门指令，开阀时长"+remotecontrol.getRainwaterOpenLength()+"小时"+"，采样方式："+DictionaryEnums.find(Integer.parseInt(remotecontrol.getSamplingMode())).getMsg()+"，同时采样数："+remotecontrol.getRainwaterSamplingNumber()+"瓶，"+publicSamOperation(remotecontrol);
		}else{
			operation = name+"下发开阀门指令，开阀时长"+remotecontrol.getRainwaterOpenLength()+"小时";
		}
		return operation;
	}
}
